package com.jason.exp.service.impl;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.jason.exp.entity.User;
import com.jason.exp.exception.ServiceException;
import com.jason.exp.mapper.UserMapper;
import com.jason.exp.service.UserService;
import com.jason.exp.utils.Clock;
import com.jason.exp.utils.Identities;
import com.jason.exp.utils.StringUtil;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * Created by fuyongde on 2016/8/31.
 */
@Service
public class UserServiceImpl implements UserService {

    Clock clock = Clock.DEFAULT;

    static LoadingCache<String, Integer> activateCodeCache = CacheBuilder.newBuilder().expireAfterWrite(5, TimeUnit.MINUTES).build(new CacheLoader<String, Integer>() {
        @Override
        public Integer load(String key) throws Exception {
            Integer code = RandomUtils.nextInt(1000, 9999);
            return code;
        }
    });

    @Resource
    private UserMapper userMapper;

    @Autowired
    private JavaMailSenderImpl mailSender;

    @Override
    public User findById(String userId) {
        if (StringUtils.isEmpty(userId)) {
            throw new ServiceException("用户id为空");
        }

        User result = userMapper.findById(userId);
        return result;
    }

    @Transactional
    @Override
    public User registerUser(User user) {
        if (StringUtils.isEmpty(user.getUsername())) {
            throw new ServiceException("用户名为空");
        }
        if (this.isExist(user.getUsername())) {
            throw new ServiceException("该用户名已存在");
        }
        String id = Identities.genId();
        user.setId(id);
        if (StringUtils.isBlank(user.getHead())) {
            String head = User.HEAD_DEFAULT;
            user.setHead(head);
        }
        if (null == user.getSex()) {
            Integer sex = User.Sex.unknown.getValue();
            user.setSex(sex);
        }
        user.setStatus(User.Status.init.getValue());
        if (null == user.getSource()) {
            Integer source = User.Source.unknown.getValue();
            user.setSource(source);
        }
        Long now = clock.getCurrentTimeInMillis();
        user.setCreated(now);
        user.setUpdated(now);
        userMapper.addOne(user);
        return user;
    }

    @Override
    public boolean isExist(String username) {
        if (StringUtils.isBlank(username)) {
            throw new ServiceException("用户名为空");
        }

        User user = userMapper.findByUsername(username);
        boolean result = false;
        if (user != null) {
            result = true;
        }
        return result;
    }

    @Transactional
    @Override
    public void sendActivateMail(String userId, String email) {
        //查找用户
        User user = this.findById(userId);
        if (user == null) {
            throw new ServiceException("该用户不存在");
        }
        if (StringUtils.isBlank(email)) {
            //TODO 邮箱格式的正则表达式
            throw new ServiceException("邮箱为空");
        }
        if (!StringUtils.equals(user.getEmail(), email)) {
            user.setEmail(email);
            user.setUpdated(clock.getCurrentTimeInMillis());
            userMapper.updateUserEmail(user);
        }
        try {
            Integer code = activateCodeCache.get(userId);
            SimpleMailMessage mailMessage = new SimpleMailMessage();
            mailMessage.setTo(email);
            mailMessage.setFrom(mailSender.getUsername());
            mailMessage.setSubject("激活");
            mailMessage.setText(String.valueOf(code));
            mailSender.send(mailMessage);
        } catch (ExecutionException e) {
            throw new ServiceException("产生激活码失败");
        }

    }

    @Transactional
    @Override
    public void updateUserEmail(String userId, String email) {
        User user = this.findById(userId);
        if (user == null) {
            throw new ServiceException("该用户不存在");
        }
        if (!StringUtils.equals(user.getEmail(), email)) {
            user.setEmail(email);
            user.setUpdated(clock.getCurrentTimeInMillis());
            userMapper.updateUserEmail(user);
        }
    }

    @Transactional
    @Override
    public void updateUserPhone(String userId, String phone) {
        User user = this.findById(userId);
        if (user == null) {
            throw new ServiceException("该用户不存在");
        }
        if (!StringUtils.equals(user.getEmail(), phone)) {
            user.setPhone(phone);
            user.setUpdated(clock.getCurrentTimeInMillis());
            userMapper.updateUserPhone(user);
        }
    }

    @Transactional
    @Override
    public void activateUser(String userId) {
        User user = this.findById(userId);
        if (user == null) {
            throw new ServiceException("该用户不存在");
        }
        user.setStatus(User.Status.activate.getValue());
        user.setUpdated(clock.getCurrentTimeInMillis());
        userMapper.activateUser(user);
    }

    @Transactional
    @Override
    public void activateUser(String userId, Integer code) {
        if (code == null) {
            throw new ServiceException("激活码为空");
        }
        try {
            Integer codeCache = activateCodeCache.get(userId);
            if (codeCache.intValue() == code.intValue()) {
                activateUser(userId);
            } else {
                throw new ServiceException("验证码错误");
            }
        } catch (ExecutionException e) {
            throw new ServiceException("验证码错误");
        }
    }
}
